#include "util.hpp"
#include "Task.hpp"
#include "ThreadPool.hpp"

class tcpServer
{
public:
    tcpServer(uint16_t port, string ip = "")        
        :_sockfd(-1),_ip(ip), _port(port)
    {
    }
    ~tcpServer()
    {
    }

    void Init()
    {
        _sockfd = socket(AF_INET, SOCK_STREAM, 0);
        if (_sockfd < 0)
        {
            Log(FATAL, "server:%s", strerror(errno));
            exit(SOCKET_ERR);
        }
        Log(DEBUG, "server create success");
        struct sockaddr_in local;
        bzero(&local, sizeof(local));
        local.sin_family = PF_INET;
        local.sin_port = htons(_port);
        //_ip.empty() ? (local.sin_addr.s_addr = INADDR_NONE) : inet_aton(_ip.c_str(),&local.sin_addr);
        local.sin_addr.s_addr = INADDR_ANY;
        // 绑定
        if (bind(_sockfd, (const struct sockaddr*)&local, sizeof(local)) != 0)
        {
           Log(FATAL, "server bind:%s", strerror(errno));
           exit(BIND_ERR);
        }
        // 监听
        if (listen(_sockfd, 5) != 0)
        {
           Log(FATAL, "server listen:%s", strerror(errno));
           exit(LISTER_ERR);
        }
        Log(DEBUG ,"listen:%s", strerror(errno));
        // 启动线程池
        _tp = ThreadPool<Task>::getInstance();
        _tp->start();
    }

    void loop()
    {
        //方案一：屏蔽信号
        //signal(SIGCHLD, SIG_IGN);
        cout << "开始工作" << endl;
        while(true)
        {
            struct sockaddr_in client;
            socklen_t len = sizeof(client);
            cout << "开始监听" << endl;
            int clientSock = accept(_sockfd, (struct sockaddr*)&client, &len);
            if (clientSock < 0)
            {
                Log(WARNING, "accept: %s[%d]", strerror(errno), clientSock);
                continue;
            }
            uint16_t clientPort = ntohs(client.sin_port);
            string clientIp = inet_ntoa(client.sin_addr);
            // 单进程版本
            //transService(clientSock, clientIp, clientPort);
            //多进程版本 
            //方案2 孤儿进制 让操作系统帮忙管理
           // pid_t id = fork(); 
           // if (id == 0)
           // {
           //     close(_sockfd);
           //     if (fork() > 0)
           //     {
           //         exit(0);
           //     } 
           //     transService(clientSock, clientIp, clientPort);
           // }
           // //父进程
           // close(clientSock);
           // pid_t ret = waitpid(id, nullptr, 0);
           // (void)ret;
            
            // 多线程版
            Task t(bind(&tcpServer::transService, this, placeholders::_1, placeholders::_2, placeholders::_3), clientSock, clientIp, clientPort);
            _tp->push(t);
        }
    }

    void transService(int sock, string ip, uint16_t port)
    {
        assert(sock >0 && !ip.empty() && port > 1024);
        char inbuffer[BUFFER_SIZE];
        while (true)
        {
            ssize_t s = read(sock, inbuffer, BUFFER_SIZE - 1);
            if (s > 0)
            {
                inbuffer[s] = '\0';
                if (strcasecmp("quit" , inbuffer) == 0)
                {
                    Log(NOTICE, "client quit -- %s[%d]", ip.c_str(), port);
                    break;
                }

                for (int i = 0 ; i < s; ++i)
                {
                    if (isalpha(inbuffer[i]) && islower(inbuffer[i]))
                    {
                        inbuffer[i] = toupper(inbuffer[i]);
                    }
                }

                write(sock, inbuffer, s);
            }
            else if (s == 0)
            {
                //对端关闭
                Log(NOTICE, "client quit -- %s[%d]", ip.c_str(), port); 
                break;
            }
            else 
            {
                Log(WARNING, "%s[%d] -- read:%s", ip.c_str(), port, strerror(errno));
                break;
            }
        } 
        close(sock);
        Log(DEBUG, "server close %d done", sock);
    }
private:
    int _sockfd;
    string _ip;
    uint16_t _port;
    ThreadPool<Task>* _tp;
};

static void Usage(string proc)
{
    cerr << "Usage: " << proc << "port [ip]" << endl;
}

int main(int argc, char* argv[])
{
    if (argc != 3 && argc != 2)
    {
        Usage(argv[0]);
        exit(USAGE_ERR);
    }

    uint16_t port = atoi(argv[1]);
    string ip;
    if (argc == 3)
    {
        ip = argv[2];
    }

    tcpServer svr(port ,ip);
    svr.Init();
    svr.loop();
    return 0;
}
